package com.element.oauth2.resource.filter;

import com.common.core.config.SpringApplicationContext;
import com.common.core.exception.ExceptionFactory;
import com.common.core.exception.code.SecurityErrorCode;
import com.element.oauth2.model.entity.AuthUserE;
import com.element.oauth2.resource.config.PermitAllUrlProperties;
import com.element.oauth2.resource.context.SecurityContext;
import com.element.oauth2.utils.PathMatcherUtil;
import com.element.oauth2.utils.SecurityUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import reactor.util.annotation.NonNull;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;

/**
 * @auther WuJun.Zhang
 * @date 2022/3/23 下午12:03
 */
@Component
@ConditionalOnClass(GlobalSecurityFilter.class)
public class SecurityHandlerInterceptor implements AsyncHandlerInterceptor {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             @NonNull HttpServletResponse response,
                             @NonNull Object handler) {
        String url = request.getServletPath();
        logger.info("url={}", url);
        PermitAllUrlProperties permitAllUrlProperties = SpringApplicationContext.getContext().getBean(PermitAllUrlProperties.class);
        List<String> ignoreUrls = permitAllUrlProperties.getIgnoreUrls();
        if (permitAllUrlProperties.hasMatcher(url)) {
            return true;
        }
        Set<String> scopeUrls = SecurityUtil.getScopeUrls();
        if (!CollectionUtils.isEmpty(scopeUrls)) {
            if (!PathMatcherUtil.hasMatcher(scopeUrls, url)) {
                throw ExceptionFactory.bizException(SecurityErrorCode.A_ACCESS_DENIED_API);
            }
        }
        AuthUserE authUser = SecurityUtil.getUser();
        if (null != authUser) {
            SecurityContext.putUser(authUser);
        }
        String appId = SecurityUtil.getAppId();
        if (!StringUtils.hasText(appId)) {
            SecurityContext.putAppId(appId);
        }
        return true;
    }

    /**
     * 请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）
     */
    @Override
    public void postHandle(@NonNull HttpServletRequest request,
                           @NonNull HttpServletResponse response,
                           @NonNull Object handler,
                           ModelAndView modelAndView) {
        SecurityContext.removeUser();
        SecurityContext.removeAppId();
    }
}
